/******************************************************************************
 * SAGE - Scalable Adaptive Graphics Environment
 *
 * Module: sageRLE.cpp - RLE comrpession for pixel block
 * Author : Luc Renambot, Byungil Jeong
 *
 * Copyright (C) 2006 Electronic Visualization Laboratory,
 * University of Illinois at Chicago
 *
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the distribution.
 *  * Neither the name of the University of Illinois at Chicago nor
 *    the names of its contributors may be used to endorse or promote
 *    products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Direct questions, comments etc about SAGE to bijeong@evl.uic.edu or 
 * http://www.evl.uic.edu/cavern/forum/
 *
 *****************************************************************************/
#include "sageBase.h"
#include "sageRLE.h"

int CompressColorRLE(unsigned char *buffer, image_ARLE *IMAGE)
{
   int i;
   unsigned char r,g,b;
   acolor prev;
   int bsize;

   bsize = IMAGE->width*IMAGE->height;
   memset(IMAGE->data, 0, bsize*sizeof(pix_t));

   r = buffer[0];
   g = buffer[1];
   b = buffer[2];

   IMAGE->size = 0;
   IMAGE->data[IMAGE->size].len = 1;
   IMAGE->data[IMAGE->size].r   = r;
   IMAGE->data[IMAGE->size].g   = g;
   IMAGE->data[IMAGE->size].b   = b;

   prev.r = r;
   prev.g = g;
   prev.b = b;

   IMAGE->size = IMAGE->size + 1;

   for (i=1;i<bsize;i++) {
      r = buffer[3*i + 0];
      g = buffer[3*i + 1];
      b = buffer[3*i + 2];
      
      if ( r == prev.r && g == prev.g && b == prev.b &&
         IMAGE->data[IMAGE->size-1].len < 254) {
         IMAGE->data[IMAGE->size-1].len = IMAGE->data[IMAGE->size-1].len + 1;
      }   
      else {
         if ( int(IMAGE->size * sizeof(pix_t)) > (IMAGE->width*IMAGE->height*3) ) {
            // Compression is not working, buffer getting too big
            return 0;
         }
         else {
            IMAGE->data[IMAGE->size].len = 1;
            IMAGE->data[IMAGE->size].r   = r;
            IMAGE->data[IMAGE->size].g   = g;
            IMAGE->data[IMAGE->size].b   = b;
            prev.r = r;
            prev.g = g;
            prev.b = b;
            IMAGE->size = IMAGE->size + 1;
         }
      }
   }

   // If success, return the size in bytes
   return ( IMAGE->size * sizeof(pix_t) );
}

int DecompressColorRLE(unsigned char *buffer, image_ARLE *IMAGE)
{
   // decoding
   int i, k, idx = 0;
   if (IMAGE->size == 0 ) {
      std::cout << "DecompressColorRLE : no image data" << std::endl;
      return 0;
   }

   for (i=0;i<IMAGE->size/4.0;i++) {
      if (IMAGE->data[i].len == 0 ) {
         std::cout << "DecompressColorRLE : imageData " << i << " data len = zero" << std::endl;
         return 0;
      }   

      for (k=0;k<IMAGE->data[i].len;k++) {
         buffer[3*idx+0] = IMAGE->data[i].r;
         buffer[3*idx+1] = IMAGE->data[i].g;
         buffer[3*idx+2] = IMAGE->data[i].b;
         idx += 1;
      }
   }
   return 1;
}

int gpuRLE(unsigned char *buffer, image_ARLE *IMAGE, unsigned char *index)
{
   int bsize;

   bsize = IMAGE->width*IMAGE->height;
   IMAGE->size = 0;

   int i = 0;
   while (i < bsize) {
      IMAGE->data[IMAGE->size].len = index[i];
      IMAGE->data[IMAGE->size].r = buffer[3*i + 0];
      IMAGE->data[IMAGE->size].g = buffer[3*i + 1];
      IMAGE->data[IMAGE->size].b = buffer[3*i + 2];
      IMAGE->size = IMAGE->size + 1;
      
      if ( int(IMAGE->size * sizeof(pix_t)) > (IMAGE->width*IMAGE->height*3) ) {
         // Compression is not working, buffer getting too big
         return 0;   
      }
       
      //std::cout << "index " << (int)index[i] << std::endl;
      i += (int)index[i];
   }

   // If success, return the size in bytes
   return ( IMAGE->size * sizeof(pix_t) );
}
